package com.sinping.qh.utils.pdf;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.Pipeline;
import com.itextpdf.tool.xml.XMLWorker;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.itextpdf.tool.xml.html.CssAppliersImpl;
import com.itextpdf.tool.xml.html.Tags;
import com.itextpdf.tool.xml.net.FileRetrieve;
import com.itextpdf.tool.xml.net.ReadingProcessor;
import com.itextpdf.tool.xml.parser.XMLParser;
import com.itextpdf.tool.xml.pipeline.css.CSSResolver;
import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline;
import com.itextpdf.tool.xml.pipeline.end.PdfWriterPipeline;
import com.itextpdf.tool.xml.pipeline.html.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.xhtmlrenderer.pdf.ITextRenderer;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.nio.charset.Charset;


public class PdfGenerator {

    /**
     * Output a pdf to the specified outputstream
     *
     * @param htmlStr the htmlstr
     * @param out     the specified outputstream
     * @throws Exception
     */
    public static void generate(String htmlStr, OutputStream out)
            throws Exception {
        DocumentBuilder builder = DocumentBuilderFactory.newInstance()
                .newDocumentBuilder();
        org.w3c.dom.Document doc = builder.parse(new ByteArrayInputStream(htmlStr
                .getBytes()));
        ITextRenderer renderer = new ITextRenderer();
        renderer.setDocument(doc, null);
        renderer.layout();
        renderer.createPDF(out);
        out.close();
    }

    public static void generatePlus(String htmlStr, OutputStream out,String urlPath) throws IOException, DocumentException {
        final String charsetName = "UTF-8";

        Document document = new Document(PageSize.A4, 30, 30, 30, 30);
        document.setMargins(30, 30, 30, 30);
        PdfWriter writer = PdfWriter.getInstance(document, out);
        document.open();

        // html内容解析
        HtmlPipelineContext htmlContext = new HtmlPipelineContext(
                new CssAppliersImpl(new XMLWorkerFontProvider() {
                    @Override
                    public Font getFont(String fontname, String encoding,
                                        float size, final int style) {
                        Font font = null;
                        if (fontname == null) {
                            //字体
                            String fontCn = getChineseFont();
                            BaseFont bf;
                            try {
                                //注意这里有一个,1
                                bf = BaseFont.createFont(fontCn + ",1",
                                        BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
                                font = new Font(bf, size, style);
                            } catch (DocumentException e) {
                                e.printStackTrace();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }

                        }
                        return font;
                    }
                })) {
            @Override
            public HtmlPipelineContext clone()
                    throws CloneNotSupportedException {
                HtmlPipelineContext context = super.clone();
                try {
                    ImageProvider imageProvider = this.getImageProvider();
                    context.setImageProvider(imageProvider);
                } catch (NoImageProviderException e) {
                }
                return context;
            }
        };

        // 图片解析
        htmlContext.setImageProvider(new AbstractImageProvider() {

            String rootPath = PdfGenerator.class.getResource("/").getPath();

            @Override
            public String getImageRootPath() {
                return rootPath;
            }

            @Override
            public Image retrieve(String src) {
                if (StringUtils.isEmpty(src)) {
                    return null;
                }
                try {
                    Image image = null;
                    if (StringUtils.isNotBlank(src) && src.contains("http")) {
                        image = Image.getInstance(src);
                    } else if (StringUtils.isNotBlank(src)) {
//                        image = Image.getInstance(new File(rootPath, src).toURI().toString());
                        image = Image.getInstance(urlPath + src);
                    }
                    // 图片显示位置
                    image.setAbsolutePosition(40, 40);
                    if (image != null) {
                        store(src, image);
                        return image;
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                }
                return super.retrieve(src);
            }
        });
        htmlContext.setAcceptUnknown(true).autoBookmark(true).setTagFactory(Tags.getHtmlTagProcessorFactory());

        // css解析
        CSSResolver cssResolver = XMLWorkerHelper.getInstance().getDefaultCssResolver(true);
        cssResolver.setFileRetrieve(new FileRetrieve() {
            @Override
            public void processFromStream(final InputStream in,
                                          final ReadingProcessor processor) throws IOException {
                InputStreamReader reader = null;
                try {
                    reader = new InputStreamReader(in, charsetName);
                    int i = 0;
                    String result="";
                    while (result!=null) {
                        i = reader.read();
                        if(i!=-1) {
                            processor.process(i);
                        }
                        else
                        {
                            result=null;
                        }
                    }
                } catch (Throwable e) {
                } finally {
                    reader.close();
                }
            }

            // 解析href
            @Override
            public void processFromHref(final String href, final ReadingProcessor processor) throws IOException {
                InputStream is = PdfGenerator.class.getResourceAsStream("/" + href);
                InputStreamReader reader = null;
                try {
                    reader = new InputStreamReader(is, charsetName);
                    int i = 0;
                    String result="";
                    while (result!=null) {
                        i = reader.read();
                        if(i!=-1) {
                            processor.process(i);
                        }
                        else
                        {
                            result=null;
                        }
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        });

        HtmlPipeline htmlPipeline = new HtmlPipeline(htmlContext, new PdfWriterPipeline(document, writer));
        Pipeline<?> pipeline = new CssResolverPipeline(cssResolver, htmlPipeline);
        XMLWorker worker = null;
        worker = new XMLWorker(pipeline, true);
        XMLParser parser = new XMLParser(true, worker, Charset.forName(charsetName));
        try {
            InputStream inputStream = new ByteArrayInputStream(htmlStr.getBytes());

            parser.parse(inputStream, Charset.forName(charsetName));
        } catch (Exception e) {

        }
        document.close();
    }

    /**
     * 获取中文字体位置
     *
     * @return
     */
    private static String getChineseFont() {

        String chineseFont = null;
        chineseFont = PdfGenerator.class.getResource("/").getPath() + "font/SIMSUN.TTC";
        if (!new File(chineseFont).exists()) {
            throw new RuntimeException("字体文件不存在,影响导出pdf中文显示！" + chineseFont);
        }

        return chineseFont;
    }
}
